home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / Rectangle.C < prev    next >
C/C++ Source or Header  |  1992-04-27  |  8KB  |  369 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "Rectangle.h"
  6.  
  7. #include "Class.h"
  8. #include "Error.h"
  9. #include "Math.h"
  10. #include "String.h"
  11.  
  12. const Rectangle gRect0;
  13.  
  14. SimpleMetaImpl(Rectangle)
  15. {
  16.     len= len;
  17.     if (! isptr)
  18.     sprintf(buf, "%s", ((Rectangle*) addr)->AsString());
  19. }
  20.  
  21. Rectangle::Rectangle()
  22. {
  23.     origin.x= origin.y= extent.x= extent.y= 0;
  24. }
  25.  
  26. Rectangle::Rectangle(int x, int y, int w, int h)
  27. {
  28.     origin.x= x;
  29.     origin.y= y;
  30.     extent.x= w;
  31.     extent.y= h;
  32. }
  33.  
  34. Rectangle::Rectangle(Point o, Point e)
  35. {
  36.     origin= o;
  37.     extent= e;
  38. }
  39.     
  40. Rectangle::Rectangle(Point e)
  41. {
  42.     origin= 0;
  43.     extent= e;
  44. }
  45.  
  46. Rectangle::Rectangle(int w, int h)
  47. {   
  48.     origin.x= origin.y= 0;
  49.     extent.x= w;
  50.     extent.y= h;
  51. }
  52.  
  53. Rectangle::Rectangle(const Rectangle &r)
  54. {
  55.     origin.x= r.origin.x;
  56.     origin.y= r.origin.y;
  57.     extent.x= r.extent.x;
  58.     extent.y= r.extent.y;
  59. }
  60.  
  61. Rectangle NormRect(Point p1, Point p2)
  62. {
  63.     Rectangle r;
  64.     
  65.     r.origin.x= Math::Min(p1.x, p2.x);
  66.     r.origin.y= Math::Min(p1.y, p2.y);
  67.     r.extent.x= Math::Max(p1.x, p2.x)+1-r.origin.x;
  68.     r.extent.y= Math::Max(p1.y, p2.y)+1-r.origin.y;
  69.     return r;
  70. }
  71.  
  72. bool Rectangle::Intersects(const Rectangle &r) const
  73. {
  74.     return origin.x < r.origin.x + r.extent.x
  75.             && r.origin.x < origin.x + extent.x
  76.             && origin.y < r.origin.y + r.extent.y
  77.             && r.origin.y < origin.y + extent.y;
  78. }
  79.  
  80. bool Rectangle::ContainsRect(const Rectangle &r) const
  81. {
  82.     Point c1= origin + extent, c2= r.origin + r.extent;
  83.     
  84.     return    origin.x <= r.origin.x && c1.x >= c2.x
  85.        && origin.y <= r.origin.y && c1.y >= c2.y;
  86. }
  87.  
  88. bool Rectangle::OvalContainsRect(const Rectangle &r) const
  89. {
  90.     int rad= Math::Min(extent.x, extent.y)/2;
  91.     Point c= Center();
  92.     
  93.     if (Length(r.NW()-c) >= rad)
  94.     return FALSE;
  95.     if (Length(r.NE()-c) >= rad)
  96.     return FALSE;
  97.     if (Length(r.SW()-c) >= rad)
  98.     return FALSE;
  99.     if (Length(r.SE()-c) >= rad)
  100.     return FALSE;
  101.     return TRUE;
  102. }
  103.  
  104. Rectangle Rectangle::Merge(const Rectangle &r)
  105.     register int x1, x2, y1, y2;
  106.     
  107.     if (IsEmpty())
  108.     return *this= r;
  109.     if (r.IsEmpty())
  110.     return *this;
  111.     x1= origin.x + extent.x; 
  112.     y1= origin.y + extent.y; 
  113.     x2= r.origin.x + r.extent.x; 
  114.     y2= r.origin.y + r.extent.y; 
  115.     origin.x= Math::Min(origin.x, r.origin.x);
  116.     origin.y= Math::Min(origin.y, r.origin.y);
  117.     extent.x= Math::Max(x1, x2) - origin.x;
  118.     extent.y= Math::Max(y1, y2) - origin.y;
  119.     return *this;
  120. }
  121.  
  122. Rectangle Union(const Rectangle &r1, const Rectangle &r2)
  123. {
  124.     Rectangle rr= r1;
  125.     return rr.Merge(r2);
  126. }
  127.  
  128. bool Rectangle::Clip(const Rectangle &r)
  129. {
  130.     register int p1x, p1y, p2x, p2y;
  131.     
  132.     if (IsEmpty())
  133.     return FALSE;
  134.     if (r.IsEmpty()) { 
  135.     *this= gRect0; // g++ 1.37.2.beta bug on 68020 cpu ?
  136.     return FALSE;
  137.     }
  138.     p1x= origin.x + extent.x;
  139.     p1y= origin.y + extent.y;
  140.     p2x= r.origin.x + r.extent.x;
  141.     p2y= r.origin.y + r.extent.y;
  142.     origin.x= Math::Max(origin.x, r.origin.x);
  143.     origin.y= Math::Max(origin.y, r.origin.y);
  144.     extent.x= Math::Min(p1x, p2x) - origin.x;
  145.     extent.y= Math::Min(p1y, p2y) - origin.y;
  146.     return IsNotEmpty();
  147. }
  148.  
  149. Rectangle Inter(Rectangle r1, const Rectangle &r2)
  150. {
  151.     r1.Clip(r2);
  152.     return r1;
  153. }
  154.  
  155. Rectangle Rectangle::Intersect(const Rectangle &r)
  156. {
  157.     Clip(r);
  158.     return *this;
  159. }
  160.  
  161. Rectangle BoundingBox(int npts, Point *pts, Point *np)
  162. {
  163.     Point mi= pts[0], ma= pts[0];
  164.     Rectangle r;
  165.     register int i;
  166.     
  167.     if (np == 0)
  168.     np= pts;
  169.     
  170.     for (i= 1; i<npts; i++) {
  171.     mi= Min(mi, pts[i]);
  172.     ma= Max(ma, pts[i]);
  173.     }
  174.     r.origin= mi;
  175.     r.extent= ma-mi+1;
  176.     for (i= 0; i<npts; i++)
  177.     np[i]= pts[i]-mi;
  178.     
  179.     return r;
  180. }
  181.  
  182. Rectangle Rectangle::WedgeBBox(int s, int d)
  183. {
  184.     Point mi, ma, p;
  185.     register int i;
  186.     
  187.     if (d >= 270)
  188.     return *this;
  189.     
  190.     mi= ma= Center();
  191.     p= AngleToPoint(s);
  192.     mi= Min(p, mi);
  193.     ma= Max(p, ma);
  194.     i= 1;
  195.     for (i= 1; i < d-1; i++) {
  196.     switch (s+i) {
  197.     case 0:
  198.         mi.y= origin.y;
  199.         break;
  200.     case 90:
  201.         ma.x= origin.x + extent.x;
  202.         break;
  203.     case 180:
  204.         ma.y= origin.y + extent.y;
  205.         break;
  206.     case 270:
  207.         mi.x= origin.x;
  208.         break;
  209.     default:
  210.         continue;
  211.     }
  212.     }
  213.     p= AngleToPoint(s+d);
  214.     return NormRect(Min(p, mi), Max(p, ma));
  215. }
  216.  
  217. int Difference(Rectangle *rp, const Rectangle &r1, const Rectangle &ra)
  218. {
  219.     register int p2x, p2y;
  220.     Rectangle r2, dr[4];
  221.     int n, i;
  222.  
  223.     r2= Inter(r1, ra);
  224.     if (r2.IsNotEmpty()) {
  225.     p2x= r2.origin.x+r2.extent.x;
  226.     p2y= r2.origin.y+r2.extent.y;
  227.     
  228.     dr[0].origin= r1.origin;
  229.     dr[0].extent.x= r1.extent.x;
  230.     dr[0].extent.y= r2.origin.y-r1.origin.y;
  231.     
  232.     dr[1].origin.x= r1.origin.x;
  233.     dr[1].origin.y= r2.origin.y;
  234.     dr[1].extent.x= r2.origin.x-r1.origin.x;
  235.     dr[1].extent.y= r2.extent.y;
  236.     
  237.     dr[2].origin.x= p2x;
  238.     dr[2].origin.y= r2.origin.y;
  239.     dr[2].extent.x= r1.origin.x+r1.extent.x-p2x;
  240.     dr[2].extent.y= r2.extent.y;
  241.     
  242.     dr[3].origin.x= r1.origin.x;
  243.     dr[3].origin.y= p2y;
  244.     dr[3].extent.x= r1.extent.x;
  245.     dr[3].extent.y= r1.origin.y+r1.extent.y-p2y;
  246.     } else 
  247.     dr[0]= r1;
  248.     
  249.     for (n= i= 0; i<4; i++)
  250.     if (dr[i].IsNotEmpty())
  251.         rp[n++]= dr[i];
  252.     return n;
  253. }
  254.  
  255. Rectangle Rectangle::Inset(Point p)
  256. {
  257.     Rectangle r;
  258.     
  259.     r.origin.x= origin.x + p.x;
  260.     r.origin.y= origin.y + p.y;
  261.     r.extent.x= extent.x - 2 * p.x;
  262.     r.extent.y= extent.y - 2 * p.y;
  263.     return r;
  264. }
  265.  
  266. Rectangle Rectangle::Expand(Point p)
  267. {
  268.     Rectangle r;
  269.     
  270.     r.origin.x= origin.x - p.x;
  271.     r.origin.y= origin.y - p.y;
  272.     r.extent.x= extent.x + 2 * p.x;
  273.     r.extent.y= extent.y + 2 * p.y;
  274.     return r;
  275. }
  276.         
  277. Point Rectangle::Constrain(Point p)
  278. {
  279.     p= Min(p, origin+extent);
  280.     return Max(p, origin);
  281. }
  282.         
  283. Point ConstrainMoveRect(const Rectangle &r1, const Rectangle &r2, Point delta)
  284. {
  285.     Point p= r1.origin + r1.extent - r2.extent;
  286.     p= Min(p, r2.origin+delta);
  287.     return Max(r1.origin, p)-r2.origin;
  288. }
  289.  
  290. Point Rectangle::AmountToTranslateWithin(const Rectangle &r)
  291. {
  292.     Point delta(0), rUL= NW(), rLR= SE(), vrUL= r.NW(), vrLR= r.SE();
  293.     
  294.     for (int v= 0; v <= 1; v++) {
  295.     if (rUL[v] < vrUL[v] && rLR[v] > vrLR[v])
  296.         continue;
  297.     if (rLR[v] - vrUL[v] < extent[v])
  298.         delta[v]= vrUL[v] - rUL[v];
  299.     if (vrLR[v] - rUL[v] < extent[v])
  300.         delta[v]= vrLR[v] - rLR[v];
  301.     }
  302.     return delta;
  303. }
  304.  
  305. OStream& operator<< (OStream &s, const Rectangle &r)
  306. {
  307.     return s << r.origin << r.extent;
  308. }                  
  309.  
  310. IStream& operator>> (IStream &s, Rectangle &r)
  311. {
  312.     return s >> r.origin >> r.extent;
  313. }
  314.  
  315. int Rectangle::PointToAngle(Point p) const
  316. {
  317.     p-= Center();
  318.     return (int) Math::Atan2(p.y*extent.x, p.x*extent.y);
  319. }
  320.  
  321. Point Rectangle::OvalAngleToPoint(int ang) const
  322. {
  323.     return Center() + PolarToPoint(ang, extent.x/2, extent.y/2);
  324. }
  325.  
  326. Point Rectangle::AngleToPoint(int a) const
  327. {
  328.     double si, co;
  329.     register int x= 0, y= 0;
  330.  
  331.     Math::Sincos(a, &si, &co);
  332.     
  333.     if (si != 0.0) {
  334.     x= (int) ((1.0 + co/Math::Abs(si))/2.0 * extent.x);
  335.     x= Math::Range(0, extent.x, x);
  336.     } else if (co >= 0.0)
  337.     x= extent.x;
  338.     if (co != 0.0) {
  339.     y= (int) ((1.0 + si/Math::Abs(co))/2.0 * extent.y);
  340.     y= Math::Range(0, extent.y, y);
  341.     } else if (si >= 0.0)
  342.     y= extent.y;
  343.     return origin + Point(x, y);
  344. }
  345.  
  346. // Corners:
  347. //         7|0|1
  348. //        -------
  349. //         6| |2
  350. //        -------
  351. //         5|4|3
  352.  
  353. int Rectangle::PointToCorner(Point p) const
  354. {
  355.     return ((PointToAngle(p)+22)/45) % 8;
  356. }
  357.  
  358. Point Rectangle::CornerToPoint(int n) const
  359. {
  360.     return AngleToPoint((n % 8)*45);
  361. }
  362.  
  363. char *Rectangle::AsString() const
  364. {
  365.     return form("x: %d y: %d w: %d h: %d", origin.x, origin.y, extent.x, extent.y);
  366. }
  367.  
  368.